package org.budo.dubbo.protocol.http.dispatcher.cometd;

import javax.servlet.ServletContext;

import org.budo.dubbo.protocol.http.dispatcher.DispatcherSupport;
import org.cometd.bayeux.server.BayeuxServer;
import org.cometd.bayeux.server.ServerTransport;
import org.cometd.server.BayeuxServerImpl;
import org.cometd.server.transport.JSONPTransport;
import org.cometd.server.transport.JSONTransport;
import org.cometd.websocket.server.WebSocketTransport;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.web.context.ServletContextAware;

/**
 * @author lmw
 */
public class BudoBayeuxServerFactoryBean extends DispatcherSupport implements FactoryBean<BayeuxServer>, ServletContextAware {
    public static final String REQUEST_CHANNEL_NAME = "/request";

    public static final String RESPONSE_CHANNEL_NAME = "/response";

    private BayeuxServerImpl _bayeuxServer;

    @Override
    public void setServletContext(ServletContext servletContext) {
        this.getBayeuxServer().setOption(ServletContext.class.getName(), servletContext);
        servletContext.setAttribute(BayeuxServer.ATTRIBUTE, this.getBayeuxServer());
    }

    @Override
    public BayeuxServer getObject() throws Exception {
        return this.getBayeuxServer();
    }

    public BayeuxServerImpl getBayeuxServer() {
        if (null == this._bayeuxServer) {
            synchronized (BudoBayeuxServerFactoryBean.class) {
                if (null == this._bayeuxServer) {
                    this._bayeuxServer = this.initBayeuxServer();
                }
            }
        }

        return this._bayeuxServer;
    }

    private BayeuxServerImpl initBayeuxServer() {
        BayeuxServerImpl bayeuxServer = new BayeuxServerImpl();

        ServerTransport[] serverTransports = new ServerTransport[] { new WebSocketTransport(bayeuxServer), //
                new JSONTransport(bayeuxServer), //
                new JSONPTransport(bayeuxServer) };

        bayeuxServer.setTransports(serverTransports);

        bayeuxServer.setOption("ws.cometdURLMapping", "/cometd/*");

        // 序列化
        bayeuxServer.setOption("jsonContext", CometdJsonContext.class.getName());

        bayeuxServer.addListener(new ServerChannelListener(new ServerChannelMessageListener(this)));

        return bayeuxServer;
    }

    @Override
    public Class<?> getObjectType() {
        return BayeuxServer.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}